package com.anandsoftware.security;

import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.anandsoftware.security.impl.BlowFish;
import com.anandsoftware.security.impl.MD5;
import com.anandsoftware.security.impl.SHA1;
import com.anandsoftware.security.impl.TrippleDES;
import com.anandsoftware.system.domain.SystemInformation;

public class SecurityUtil {

	private static final Logger LOG = LoggerFactory
			.getLogger(SecurityUtil.class);

	/**
	 * 
	 * @param <T>
	 *            any class extending AbstractSecurityAlgorithm
	 * @param algorithm
	 *            type of algorithm.
	 * @return different implementation of SecurityAlgorithm
	 */
	public static <T extends AbstractSecurityAlgorithm> T getInstance(
			int algorithm) {
		T t = null;
		switch (algorithm) {
		case SecurityAlgorithm.BLOWFISH:
			t = (T) new BlowFish();
			break;
		case SecurityAlgorithm.MD5:
			t = (T) new MD5();
			break;
		case SecurityAlgorithm.SHA1:
			t = (T) new SHA1();
			break;
		case SecurityAlgorithm.TRIPPLE_DES:
			t = (T) new TrippleDES();
			break;
		default:
			return null;
		}
		LOG.info("Retriving Instance of " + t.getClass().getName());
		return t;
	}

	/**
	 * 
	 * @param systemInformation
	 *            systeminformation
	 * @param algorithm
	 *            type of algorithm to be used MD5 or SHA1
	 * @return encrypted <e(k),e(v)> representation of {@link SystemInformation}
	 *         e is a encryption function.
	 */
	public static Map<String, String> encryptPropertyAndValue(
			SystemInformation systemInformation, int algorithm) {

		LOG.info("Inside Encrypt Prop & val");
		Map<String, String> encryptedPorp = new HashMap<String, String>();
		SecurityAlgorithm encryptionAlgo = SecurityUtil.getInstance(algorithm);
		Set<String> macIds = systemInformation.getMacIdList();
		String macIdList = "";
		if (macIds != null) {
			for (String currentMacId : macIds) {
				macIdList += "," + currentMacId;
			}
		}

		encryptedPorp.put(encryptionAlgo.encrypt("macIdList"),
				encryptionAlgo.encrypt(macIdList));

		if (systemInformation.getOsName() != null) {
			encryptedPorp.put(encryptionAlgo.encrypt("osName"),
					encryptionAlgo.encrypt(systemInformation.getOsName()));
		}

		if (systemInformation.getOsVersion() != null) {
			encryptedPorp.put(encryptionAlgo.encrypt("osVersion"),
					encryptionAlgo.encrypt(systemInformation.getOsVersion()));
		}

		if (systemInformation.getOsProductKey() != null) {
			encryptedPorp
					.put(encryptionAlgo.encrypt("osProductKey"), encryptionAlgo
							.encrypt(systemInformation.getOsProductKey()));
		}

		if (systemInformation.getOsDriveSerialNumber() != null) {
			encryptedPorp.put(encryptionAlgo.encrypt("osDriveSerialNumber"),
					encryptionAlgo.encrypt(systemInformation
							.getOsDriveSerialNumber()));
		}

		if (systemInformation.getOsOriginalInstallDate() != null) {
			encryptedPorp.put(encryptionAlgo.encrypt("osOriginalInstallDate"),
					encryptionAlgo.encrypt(systemInformation
							.getOsOriginalInstallDate()));
		}

		if (systemInformation.getSystemType() != null) {
			encryptedPorp.put(encryptionAlgo.encrypt("systemType"),
					encryptionAlgo.encrypt(systemInformation.getSystemType()));
		}

		if (systemInformation.getPhysicalMemory() != null) {
			encryptedPorp.put(encryptionAlgo.encrypt("physicalMemory"),
					encryptionAlgo.encrypt(systemInformation
							.getPhysicalMemory()));
		}

		return encryptedPorp;
	}

	/**
	 * 
	 * @param systemInformation
	 *            systemInformation
	 * @param algorithm
	 *            type of algorithm to be used MD5 or SHA1
	 * @return encrypted <k,e(v)> representation of {@link SystemInformation}
	 *         where e is a encryption function
	 */
	public static SystemInformation encryptValue(

	SystemInformation systemInformation, int algorithm) {
		LOG.info("Inside Encrypt val");
		SystemInformation returnObject = new SystemInformation();
		SecurityAlgorithm encryptionAlgo = SecurityUtil.getInstance(algorithm);
		Set<String> macIds = systemInformation.getMacIdList();
		Set<String> newMacIds = new HashSet<String>();
		if (macIds != null && macIds.size() > 0) {
			for (String currentMacId : macIds) {
				newMacIds.add(encryptionAlgo.encrypt(currentMacId));
			}
			returnObject.setMacIdList(newMacIds);
		}

		if (systemInformation.getOsName() != null) {
			returnObject.setOsName(encryptionAlgo.encrypt(systemInformation
					.getOsName()));
		}

		if (systemInformation.getOsVersion() != null) {
			returnObject.setOsVersion(encryptionAlgo.encrypt(systemInformation
					.getOsVersion()));
		}

		if (systemInformation.getOsProductKey() != null) {
			returnObject.setOsProductKey(encryptionAlgo
					.encrypt(systemInformation.getOsProductKey()));
		}

		if (systemInformation.getOsDriveSerialNumber() != null) {
			returnObject.setOsDriveSerialNumber(encryptionAlgo
					.encrypt(systemInformation.getOsDriveSerialNumber()));
		}

		if (systemInformation.getOsOriginalInstallDate() != null) {
			returnObject.setOsOriginalInstallDate(encryptionAlgo
					.encrypt(systemInformation.getOsOriginalInstallDate()));
		}

		if (systemInformation.getSystemType() != null) {
			returnObject.setSystemType(encryptionAlgo.encrypt(systemInformation
					.getSystemType()));
		}

		if (systemInformation.getPhysicalMemory() != null) {
			returnObject.setPhysicalMemory(encryptionAlgo
					.encrypt(systemInformation.getPhysicalMemory()));
		}

		return returnObject;

	}
}
